#include "ipHisto.h"
#include "ImageRgb.h"
#include "ImageGray.h"
#include "Segment2D.h"
#include "Point2D.h"
#include "xtprobeImageDiskXFile.h"
#include "CmdLine.h"
#include "tp2.h"

Contraste::Contraste(char* name)
{
	image = new ImageGray();
  	image->setBOption("verbose",true);
  
  	ImageDiskXFile *image_file = new xtprobeImageDiskXFile(name,"r");

	LUT = (int*)malloc(sizeof(int)*256);

	file_name = (char*) malloc (sizeof(char)*longueur(name)+1);
	
	strcpy(file_name,name);

  	//chargement de l'image
  	image->loadImageXFile(image_file);

  	//on libere l'espace occupe par image_file
  	delete image_file; 

}

Contraste::~Contraste(){
}

void Contraste::drawHistogramme(ImageGray *img, char* image_file_name)
{
	 ipCore *histo = NULL;
  	histo = new ipHisto(img->width,img->height,"gray");
  	histo->setBOption("verbose",false);
  	histo->setBOption("normalise",false);
  	histo->process(img);

  	real *h = histo->seq_out->frames[0];
  
  	/*
  	*On cherche la valeur du pixel d'intensite maximale 
  	*
  	*/
  	int max_pixel = h[0];
  	for(int k= 0;k< 256; k++){

    		if(h[k]>max_pixel)
     	 	max_pixel = h[k];
	}
 	ImageRgb *image = new ImageRgb(256,256);

	setWhiteBackgroud(image);	

	graduateImage(image);
	
	char*name = (char*)newName(file_name,image_file_name);
  
  	DiskXFile *img_file = new DiskXFile(name,"w");
  
  	int size = 256;
  	for(int i=0;i<size;i++){

    		int h_ = (int) (h[i]*img->width*img->height);
    		if(h_ != 0){
      			image->drawline(i,256,i,(int) (256-h[i]*256/max_pixel),red);
    		}
 	}
  
  	image->saveXFile(img_file);
  
  	delete histo;
  	delete image; 
}

void Contraste::modifyImage(ImageGray *img)
{

	for(int k = 0;k<img->height;k++){
		for(int j = 0;j<img->width;j++)
			
		img->get(k,j)[0] = LUT[(int)img->get(k,j)[0]];    		
 	 } 
	
	char contrasteName[] = {'_','c','o','n','t','r','a','s','t','e','.','p','g','m','\0'};
	
	char contrastehisto[] = {'_','c','o','n','t','r','a','s','t','e','_','h','i','s','t','o','.','p','p','m','\0'};
	
	
	
	saveImage(img,contrasteName);

	ImageGray *imag = new ImageGray();
  	imag->setBOption("verbose",true);
  
  	ImageDiskXFile *imag_file = new xtprobeImageDiskXFile((char*)newName(file_name,contrasteName),"r");
	imag->loadImageXFile(imag_file);
	drawHistogramme(imag, contrastehisto);
	
	delete imag;
	delete imag_file;
	
	
}

void Contraste::saveImage(ImageGray *img, char* image_file_name){
  	DiskXFile *image_file;
  	
	char *name = (char*)newName(file_name,image_file_name);	
  	
  	image_file = new DiskXFile(name,"w");
  
  	img->saveXFile(image_file);
  
  	delete image_file;
}


int* Contraste::initLUT(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,int nbarg)
{

  int *lut = (int*) malloc(sizeof(int)*256);
  if(x1 < x2 && x1 > 0 && y2 < 255 && y1 > 0 && x2 < 255 && y1<255)
	{
		
		
		for(int i = 0;i<256;i++)
		{	
			if(i <= x1)
				lut[i] = (int)computeValue(0,0,x1,y1,i);
			else 
			if(i<x2)
				lut[i] = (int)computeValue(x1,y1,x2,y2,i);
			else
			   if(nbarg > 6 && x3 > x2 && x3<255 && y2 <255 && y3 < 255)
				if( i < x3)
					lut[i] = (int)computeValue(x2,y2,x3,y3,i);	
				else 
				   if(nbarg == 10 && x4 > x3 && x4 < 255 && y3<255 && y4 < 255)
					if(i < x4)
					     lut[i] = (int)computeValue(x3,y3,x4,y4,i); 
					else
					   lut[i] = (int)computeValue(x4,y4,255,255,i);
				   else
					lut[i] = (int)computeValue(x3,y3,255,255,i);
			   else
				lut[i] = (int)computeValue(x2,y2,255,255,i);
    		}
    		
  	} 

	return lut;
}

	/*
	*Etant donnee une droite y=ax+b, la pente de cette droite est donnee par a = (y2 - y1)/(x2 - x1) avec (x1,y1) et(x2,y2) 
	*des points de la droite
	*
	*le point (x1,y1) appartient a la droite ie y1 = ax1+b et donc b= x1 - (y2-y1)*x1/(x2-x1)
	*ainsi, pour tout point I(x,y) appartenant a la droite, y = y1 + (y2-y1)*(x - x1)/(x2 - x1)
	*
	*/

int Contraste::computeValue(int x1,int y1,int x2,int y2,int drapeau){
	
	int y = y1 + (int)((y2-y1)*(drapeau - x1)/(x2 - x1));
	if(y < 0) 
		y = 0;
	if(y > 255) 
		y = 255;
	
	return (y);
}


void Contraste::drawFunction(char* func_name, int x1, int y1, int x2, int y2,int x3, int y3, int x4, int y4,int nbarg){

	ImageRgb *img = new ImageRgb(256,256);
	

	setWhiteBackgroud(img);	

	graduateImage(img);

	if(nbarg == 6 ){
		
		img->drawline(0,255,x1,255-y1,blue);
		img->drawline(x1,255-y1,x2,255-y2,blue);
		img->drawline(x2,255-y2,255,0,blue);
	}
	else
	   if(nbarg == 8 && x3 > x2 && x3<255 && y3 > y2 && y3 < 255)
	   {

		
		img->drawline(0,255,x1,255-y1,blue);
		img->drawline(x1,255-y1,x2,255-y2,blue);
		img->drawline(x2,255-y2,x3,255-y3,blue);
		img->drawline(x3,255-y3,255,0,blue);
	   } 
	   else
		if(nbarg == 10 && x4 > x3 && x4 < 255 && y4 > y3 && y4 < 255)
		{
			
			img->drawline(0,255,x1,255-y1,blue);
			img->drawline(x1,255-y1,x2,255-y2,blue);
			img->drawline(x2,255-y2,x3,255-y3,blue);
			img->drawline(x3,255-y3,x4,255-y4,blue);
			img->drawline(x4,255-y4,255,0,blue);				
		}
	
	char*name = (char*)newName(file_name,func_name);
	
	DiskXFile *image_file;
  
  	image_file = new DiskXFile(name,"w");
  
  	img->saveXFile(image_file);
  
 	delete image_file;
}

void Contraste::graduateImage(Image *img){

	img->drawline(0,0,255,0,black);
	img->drawline(0,0,0,255,black);
	img->drawline(0,255,255,255,black);
	img->drawline(255,0,255,255,black);

	img->drawline(0,5,2,5,black);
	img->drawline(0,55,2,55,black);
	img->drawline(0,105,2,105,black);
	img->drawline(0,155,2,155,black);
	img->drawline(0,205,2,205,black);

	img->drawline(50,0,50,2,black);
	img->drawline(100,0,100,2,black);
	img->drawline(150,0,150,2,black);
	img->drawline(200,0,200,2,black);
	img->drawline(250,0,250,2,black);

	img->drawline(255,5,253,5,black);
	img->drawline(255,55,253,55,black);
	img->drawline(255,105,253,105,black);
	img->drawline(255,155,253,155,black);
	img->drawline(255,205,253,205,black);

	img->drawline(50,255,50,253,black);
	img->drawline(100,255,100,253,black);
	img->drawline(150,255,150,253,black);
	img->drawline(200,255,200,253,black);
	img->drawline(250,255,250,253,black);
	
}


void Contraste::setWhiteBackgroud(ImageRgb *img){
	for(int n=0;n<img->real_image_size;n++){
    		img->pixmap[n * 3] = 255;
    		img->pixmap[n * 3 + 1] = 255;
    		img->pixmap[n * 3 + 2] = 255;
	}	
}

int Contraste::longueur(char* chaine)
{

	int k =0;
	for(k=0;chaine[k]!='\0';k++);
	
	return(k);
		
}

char*Contraste::newName(char*oldname,char*additionName)
{
	//on soustrait 4 pour fairepartir les informations du type de l'image
	int l = longueur(oldname) - 4;
	int size = l + longueur(additionName) + 1; 

	char* nouveau = (char*)malloc(sizeof(char)*(l+longueur(additionName) + 1));
	int i = 0;
	for(i = 0;i<l;i++)
		nouveau[i] = oldname[i]; 
	//printf("\t%s\n",nouveau);
	for(int t=0,k=i; k< size;t++,k++)
		nouveau[k]=additionName[t];

	return (nouveau);
	
}

char* Contraste::readData(char**arg,char*fichier,int*x1,int*y1,int*x2,int*y2,int*x3,int*y3,int*x4,int*y4, int nbrearguments)
{
	//char* a = (char*)arg[1];
	
	char*point1 = (char*)arg[2];

	//char*b = (char*)arg[3];

	char*point2 = (char*)arg[4];
	
	char*nomfichier = (char*)arg[5];
	char *cx1=(char*) malloc (sizeof(char)*4); 
	int s = 0;
	for(s=0;point1[s]!=',';s++)
		cx1[s] = point1[s]; 
	cx1[s]='\0';
	*x1 = atoi(cx1);
 	char *cy1=(char*) malloc (sizeof(char)*4); 
	int n= 0;
	int m=0;
	for(n=s+1,m=0;point1[n]!='\0';n++,m++)
		cy1[m] = point1[n]; 
	cy1[m]='\0';
	
	*y1 = atoi(cy1);
	delete cx1; delete cy1;

	char *cx2=(char*) malloc (sizeof(char)*4); 
	int i = 0;
	for(i=0;point2[i]!=',';i++)
		cx2[i] = point2[i]; 
	cx2[i]='\0';
	*x2 = atoi(cx2);
		
 	char *cy2=(char*) malloc (sizeof(char)*4);
	int k= 0;
	int t=0;
	for(k=i+1,t=0;point2[k]!='\0';k++,t++)
		cy2[t] = point2[k]; 
	cy2[t]='\0';
	
	*y2 = atoi(cy2);
	
	delete cx2; delete cy2;

	if(nbrearguments > 6){
		//char *c =(char*)arg[5];
		char*point3 = (char*)arg[6];
		nomfichier = (char*)arg[7];

		char *cx3=(char*) malloc (sizeof(char)*4); 
		int r = 0;
		for(r=0;point3[r]!=',';r++)
		cx3[r] = point3[r]; 
		cx3[r]='\0';
		*x3 = atoi(cx3);
 		char *cy3=(char*) malloc (sizeof(char)*4); 
		int n3= 0;
		int m3=0;
		for(n3=r+1,m3=0;point3[n3]!='\0';n3++,m3++)
		cy3[m3] = point3[n3]; 
		cy3[m3]='\0';
	
		*y3 = atoi(cy3);
		delete cx3; delete cy3;

		if(nbrearguments == 10)
		{
			//char*d = (char*)arg[7];			
			char*point4 = (char*)arg[8];
			nomfichier = (char*)arg[9];
			char *cx4=(char*) malloc (sizeof(char)*4); 
			int r1 = 0;
			for(r1=0;point4[r1]!=',';r1++)
			cx4[r1] = point4[r1]; 
			cx4[r1]='\0';
			*x4 = atoi(cx4);
 			char *cy4=(char*) malloc (sizeof(char)*4); 
			int n4= 0;
			int m4=0;
			for(n4=r1+1,m4=0;point4[n4]!='\0';n4++,m4++)
			cy4[m4] = point4[n4]; 
			cy4[m4]='\0';
	
			*y4 = atoi(cy4);
			delete cx4; delete cy4;						
			
			
		}
	}
	
	
	return(nomfichier);
	
}





